package geppetto.phraseHMM.lexicalWeighting;

import geppetto.cat.alignments.Alignment;
import geppetto.cat.alignments.AlignmentsSet;
import geppetto.lexical.LexicalT;
import geppetto.phraseTable.PhraseTable;
import geppetto.phraseTable.phrase.Phrase;
import gnu.trove.TIntObjectHashMap;

import java.util.LinkedList;
import java.util.List;





public class MosesLexicalWeightingCalculator implements
		AbstractLexicalWeightingCalculator {
	LexicalT lexical;
	
	protected AlignmentsSet set;
	protected AlignmentsSet reverseSet;

	public MosesLexicalWeightingCalculator(AlignmentsSet set, LexicalT lexical) {
		super();
		this.set = set;
		this.reverseSet = set.reverse();
		this.lexical = lexical;
	}

	public double getLexicalWeight(
			int sentenceNumber, int[] sourceSentence, int[] foreingSentence,
			int sourceStartPos, int sourceEndPos, int foreignStartPos,
			int foreignEndPos) {

		return getLexicalWeightInfoForPhrase(set, sentenceNumber, sourceSentence, foreingSentence, sourceStartPos, sourceEndPos, foreignStartPos, foreignEndPos);
	}
	
	public double getReverseLexicalWeight(
			int sentenceNumber, int[] sourceSentence, int[] foreingSentence,
			int sourceStartPos, int sourceEndPos, int foreignStartPos,
			int foreignEndPos) {

		lexical.reverse();
		double ret = getLexicalWeightInfoForPhrase(reverseSet, sentenceNumber, foreingSentence, sourceSentence, foreignStartPos, foreignEndPos, sourceStartPos, sourceEndPos);
		lexical.reverse();
		return ret;
	} 

	public double getLexicalWeightInfoForPhrase(
			AlignmentsSet alignSet, int sentenceNumber,
			int[] sourceSentence, int[] foreingSentence, int sourceStartPos,
			int sourceEndPos, int foreignStartPos, int foreignEndPos) {

		Alignment al = alignSet.get(sentenceNumber);

		Integer[] sourceWords = new Integer[sourceEndPos - sourceStartPos + 1];
		Integer[][] targetWords = new Integer[sourceEndPos - sourceStartPos + 1][];

		for (int spos = sourceStartPos; spos <= sourceEndPos; spos++) {
			boolean hasAligmnent = false;
			List<Integer> targetArray = new LinkedList<Integer>();

			for (int fpos = foreignStartPos; fpos <= foreignEndPos; fpos++) {
				if (al.hasPosition(spos, fpos)) {
					hasAligmnent = true;
					targetArray.add(foreingSentence[fpos]);
				}
			}
			if (!hasAligmnent) {
				targetArray.add(-1);
			}
			sourceWords[spos - sourceStartPos] = sourceSentence[spos];
			targetWords[spos - sourceStartPos] = targetArray
					.toArray(new Integer[0]);
		}
		
		double lexicalWeighting = 1;
		for (int index = 0; index < sourceWords.length; index++) {
			Integer sourceWord = sourceWords[index];
			Integer[] targetWordsList = targetWords[index];
			double localLexicalWeighting = 0;
			for (Integer targetWord : targetWordsList) {
				if (targetWord != -1) {
					localLexicalWeighting += lexical.getProbabilitySF(
							sourceWord, targetWord)
							/ targetWordsList.length;
				} else {
					localLexicalWeighting += lexical
							.getProbabilitySF(sourceWord, LexicalT.NULL)
							/ targetWordsList.length;
				}
			}
			lexicalWeighting *= localLexicalWeighting;
		}
		return lexicalWeighting;
	}
}
